package classloader;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @ClassName DecryptClassLoader
 * @Description TODO
 * 加密类的加载器
 * @Author liang
 * @Date 2018\10\23 0023 10:43
 * @Version 1.0
 **/
public class DecryptClassLoader extends ClassLoader{
    private String rootDir;
    public DecryptClassLoader(String rootDir){
        this.rootDir = rootDir;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //查找 这个类是否已经被加载过
        Class<?> c = findLoadedClass(name);
        if(c != null){
            return c;
        }else {
            //获得父类加载器
            ClassLoader parent = this.getParent();
            try{
                c = parent.loadClass(name);
            }catch (Exception e){

            }


            if(c != null){
                return c;
            }else {
                //自己来加载
                byte[] classData = new byte[0];
                try {
                    classData = getClassData(name);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if(classData == null){
                    throw new ClassNotFoundException();
                }else {
                    //加载读取字节码
                    c = defineClass(name, classData, 0, classData.length);
                    return c;
                }
            }
        }

    }

    /**
     * 自己加载类 返回字节数组
     * 传入的路径为  com.xx.xx
     * 变成绝对路径 D:/xx/xx/
     *
     * @param name
     * @return
     */
    private byte[] getClassData(String name) throws IOException {
        String path = rootDir + "/" + name.replace(".","/")+".class";
        FileInputStream is = new FileInputStream(path);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //先解密再装载
        int temp = -1;
        while ((temp = is.read()) != -1){
            bos.write(temp ^ 0xff);
        }
        return bos.toByteArray();
    }
}
